home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 419_01 / odmg10 / config / fansi.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-28  |  11.1 KB  |  593 lines

  1. /*******************************<+>***************************
  2.  **                             DTA
  3.  *************************************************************
  4.  **
  5.  **  $Id:
  6.  **
  7.  **  $Source:
  8.  **
  9.  **  Module Name:
  10.  **
  11.  **  Classification:  Unclassified
  12.  **
  13.  **  Author:          Dale T. Anderson
  14.  **
  15.  *******************************<+>***************************/
  16.  
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <ctype.h>
  21. #ifndef linux
  22. #include <malloc.h>
  23. #endif
  24. #include <assert.h>
  25.  
  26. char **tokens = NULL;
  27.  
  28. unsigned tcount = 0;
  29. unsigned tlength = 0;
  30.  
  31. int debug = 0;
  32. int dostatic = 0;
  33. int dointernal = 0;
  34. int doverbose = 1;
  35. int douseproto = 1;
  36. int doextern = 0;
  37. int iscxx = 0;
  38. int doapi = 0;
  39.  
  40. int isblankline (str)
  41. char *str;
  42. {
  43.     while (*str && (*str == '\n' || *str == ' ' || *str == '\t'))
  44.     str++;
  45.     return (*str == 0);
  46. }
  47.  
  48. int find_token (start, str)
  49. int start;
  50. char *str;
  51. {
  52.     int i;
  53.  
  54.     for (i = start; i < tcount; i++)
  55.     if (!strcmp (str, tokens[i]))
  56.         return (i);
  57.     return (-1);
  58. }
  59.  
  60. int last_token (start, str)
  61. int start;
  62. char *str;
  63. {
  64.     int i;
  65.  
  66.     for (i = tcount - 1; i >= start; i--)
  67.     if (!strcmp (str, tokens[i]))
  68.         return (i);
  69.     return (-1);
  70. }
  71.  
  72. void add_token ()
  73. {
  74.     static int total = 0;
  75.     int i;
  76.  
  77.     if (!total || tcount == total - 1) {
  78.     total += 256;
  79.     if (tokens)
  80.         tokens = (char **) realloc ((char *) tokens, sizeof (char *) * total);
  81.     else
  82.         tokens = (char **) malloc (sizeof (char *) * total);
  83.  
  84.     for (i = tcount; i < total; i++)
  85.         tokens[i] = malloc (128);
  86.     }
  87.     if (tlength) {
  88.     assert (tlength < 80);
  89.     tokens[tcount][tlength] = 0;
  90.     if (!strcmp (tokens[tcount], "va_alist"))
  91.         strcpy (tokens[tcount], "...");
  92.     if (!strcmp (tokens[tcount], "va_dcl"))
  93.         strcpy (tokens[tcount], "...");
  94.     tlength = 0;
  95.     tcount++;
  96.     }
  97. }
  98.  
  99. void token_char (ch)
  100. char ch;
  101. {
  102.     tokens[tcount][tlength] = ch;
  103.     tlength++;
  104. }
  105.  
  106. void print_header (stream, name)
  107. FILE *stream;
  108. char *name;
  109. {
  110.     if (!iscxx) {
  111.     fprintf (stream, "\n/*\n");
  112.     fprintf (stream, " * %s\n", name);
  113.     fprintf (stream, " */\n\n");
  114.     } else {
  115.     fprintf (stream, "\n//\n");
  116.     fprintf (stream, "// %s\n", name);
  117.     fprintf (stream, "//\n\n");
  118.     }
  119. }
  120.  
  121. void print_fun (stream, beg, end)
  122. FILE *stream;
  123. int beg;
  124. int end;
  125. {
  126.     int i;
  127.  
  128.     if (!dostatic && doextern)
  129.     fprintf (stream, "extern ");
  130.  
  131.     for (i = beg; i <= end; i++) {
  132.     if (i > beg)
  133.         fputc (' ', stream);
  134.     fprintf (stream, tokens[i]);
  135.     }
  136.  
  137.     fprintf (stream, " (");
  138.  
  139.     if (douseproto)
  140.     fprintf (stream, "\n");
  141. }
  142.  
  143. typedef enum {True, False} Boolean;
  144.  
  145. static Boolean IsLastParameter(idx, end)
  146. int idx;
  147. int end;
  148. {
  149.     static Boolean in_if = False;
  150.     static Boolean in_else = False;
  151.  
  152.     if (idx == end) {
  153.     in_if = in_else = False;
  154.     return True;
  155.     }
  156. /*
  157.  * case 1:  if last token is a parameter, and not analyzing last parameter,
  158.  *  then no special cases exist
  159.  */
  160.     else if (tokens[end][0] != '#')
  161.     return False;
  162.     else if (strncmp(tokens[idx], "#if",3) == 0 || 
  163.          strncmp(tokens[idx],"#elif",5) == 0) {
  164.     in_if = True;
  165.     in_else = False;
  166.     } else if (strncmp(tokens[idx], "#else",5) == 0) {
  167.     in_else = True;
  168.     in_if = False;
  169.     } else if (strncmp(tokens[idx], "#endif", 6) == 0) {
  170.     in_else = in_if = False;
  171.     }
  172. /*
  173.  * case 2:  inside an #else or #elif, and currently on next to last token.  Last
  174.  *  token should be a #endif - else a syntax error will occur most likely
  175.  *  in C Compiler or preprocessor if missing the #endif
  176.  */
  177.     if (in_else == True && idx == (end - 1)) /*Last parameter of #else*/
  178.     return True;
  179. /*
  180.  * case 3: inside the #if..., need to find the last token in the last #if
  181.  *  clause, and if currently in that, return that this is last parameter
  182.  */
  183.     else if (in_if == True) {
  184.     int i;
  185.     for (i=idx+1; i<end; i++) {
  186.         if (tokens[i][0] == '#') {
  187.         if (i > (idx + 1))
  188.             return False;
  189.         else {
  190.             int j;
  191.             for (j=i; j<end; j++)
  192.             if (strncmp(tokens[j], "#endif", 6) == 0)
  193.                 break;
  194.             if (j == end) /*Last #endif clause - this is last parm.*/
  195.             return True;
  196.             }
  197.         }
  198.         }
  199.     }
  200.     return False;
  201. }
  202.  
  203. void print_args (stream, beg, end)
  204. FILE *stream;
  205. int beg;
  206. int end;
  207. {
  208.     int tab;
  209.     int i;
  210.  
  211.     if (douseproto)
  212.         fprintf (stream, "#ifdef UseProto\n");
  213.     if (beg > end) {
  214.     if (douseproto)
  215.         fprintf (stream, "\tvoid\n");
  216.     else
  217.         fprintf (stream, "void");
  218.     } else {
  219.     tab = tokens[beg][0] == '#' ? 0 : 1;
  220.     for (i = beg; i <= end; i++) {
  221.         if (tab) {
  222.         if (douseproto)
  223.             fputc ('\t', stream);
  224.         tab = 0;
  225.         }
  226.         (void) IsLastParameter(i,end);
  227.         if (tokens[i][0] == ';' || tokens[i][0] == ',') {
  228.         if (IsLastParameter(i, end) == False)
  229.             fputc (',', stream);
  230.         } else {
  231.         if (i && tokens[i - 1][0] != '*' && tokens[i - 1][0] != '[' &&
  232.             tokens[i][0] != '#' && i != beg) 
  233.             fputc (' ', stream);
  234.         fprintf (stream, tokens[i]);
  235.         }
  236.         if (tokens[i][0] == '#' || tokens[i][0] == ',' || 
  237.             tokens[i][0] == ';' || i == end) {
  238.         if (douseproto)
  239.             fputc ('\n', stream);
  240.         if (i != end)
  241.             tab = tokens[i+1][0] == '#' ? 0 : 1;
  242.         }
  243.     }
  244.     }
  245.     if (douseproto)
  246.         fprintf (stream, "#endif\n");
  247.  
  248.     fprintf (stream, ");\n");
  249.  
  250.     if (doverbose)
  251.     fprintf (stream, "\n");
  252. }
  253.  
  254. void tokenize (ch)
  255. char ch;
  256. {
  257.     switch (ch) {
  258.     case ' ':
  259.     case '\t':
  260.         add_token ();
  261.         break;
  262.     case '*':
  263.     case '[':
  264.     case ']':
  265.     case '(':
  266.     case ')':
  267.     case ',':
  268.     case ';':
  269.         add_token ();
  270.         token_char (ch);
  271.         add_token ();
  272.         break;
  273.     default:
  274.         token_char (ch);
  275.     }
  276. }
  277.  
  278. int add_line (buf)
  279. char *buf;
  280. {
  281.     int i;
  282.  
  283.     if (tcount > 0 && buf[0] == '#') {
  284.     (void) strcpy (tokens[tcount], buf);
  285.     tlength += strlen(buf);
  286.     tokenize(' ');
  287.     return 0;
  288.     }
  289.  
  290.     if (!strchr(buf, '=') && !strchr(buf, '#')) {
  291.     for (i = 0; buf[i]; i++)
  292.         tokenize (buf[i]);
  293.     tokenize (' ');
  294.     }
  295.     return 0;
  296. }
  297.  
  298. int valid_name (name)
  299. char *name;
  300. {
  301.     int i;
  302.  
  303.     if (!doapi && !strcmp (name, "..."))
  304.     return (0);
  305.  
  306.     if (!doapi && strstr (name, "::"))
  307.     return (-1);
  308.  
  309.     if (!strcmp (name, "main"))
  310.     return (-1);
  311.  
  312.     if (!isalpha (*name) && *name != '_')
  313.     return (-1);
  314.  
  315.     for (i = 1; name[i]; i++) {
  316.     if (!(isalpha (name[i]) || isdigit (name[i]) || name[i] == '_' || name [i] == ':'))
  317.         return (-1);
  318.     }
  319.  
  320.     return (0);
  321. }
  322.  
  323. int get_start (open_paren)
  324. int open_paren;
  325. {
  326.     int semi;
  327.     int start;
  328.  
  329.     start = 0;
  330.  
  331.     while ((semi = find_token (start, ";")) >= 0) {
  332.     if (semi < open_paren)
  333.         start = semi + 1;
  334.     else
  335.         break;
  336.     }
  337.  
  338.     return (start);
  339. }
  340.  
  341. int print_prototype (stream)
  342. FILE *stream;
  343. {
  344.     int open_paren;
  345.     int close_paren;
  346.     int start;
  347.     int i;
  348.  
  349.     if (debug && tcount) {
  350.     printf ("<");
  351.     for (i = 0; i < tcount; i++)
  352.         printf ("\t%d: %s\n", i, tokens[i]);
  353.     printf (">\n");
  354.     }
  355.  
  356.     if ((close_paren = last_token (0, ")")) < 0 || close_paren < 1)
  357.     return (-1);
  358.  
  359.     for (i = -1, open_paren = close_paren - 1; open_paren >= 0; open_paren--) {
  360.     if (tokens[open_paren][0] == '(')
  361.         i++;
  362.     else if (tokens[open_paren][0] == ')')
  363.         i--;
  364.     if (!i)
  365.         break;
  366.     }
  367.  
  368.     if (i)
  369.     return (-2);
  370.  
  371.     for (start = open_paren; start > 0; start--)
  372.     if (!strcmp (tokens [start], ";"))
  373.         break;
  374.  
  375.     for (i = start; i < open_paren; i++) {
  376.     if (tokens[i][1] && valid_name (tokens[i]) < 0)
  377.         return (-100 - i);
  378.     }
  379.  
  380.     /*
  381.      * check for token streams that should be thrown away
  382.      */
  383.  
  384.     if (!dointernal && (tokens[open_paren - 1][0] == '_'))
  385.     return (-3);
  386.  
  387.     if ((start = get_start (open_paren)) < 0)
  388.     return (-4);
  389.  
  390.     if (!strcmp (tokens[start], "extern"))
  391.     return (-5);
  392.  
  393.     if (!strcmp (tokens[start], "typedef"))
  394.     return (-5);
  395.  
  396.     if (!dostatic == (!strcmp (tokens[start], "static")))
  397.     return (-6);
  398.  
  399.     /*
  400.      * function has no return type, so too bad!
  401.      */
  402.  
  403.     while (tcount > 0 && !strcmp (tokens [tcount - 1], "const"))
  404.     tcount--;
  405.  
  406.     if (open_paren - start <= 1)
  407.     return (-7);
  408.  
  409.     /*
  410.      * print the function name and return type
  411.      */
  412.  
  413.     print_fun (stream, start, open_paren - 1);
  414.  
  415.     /*
  416.      * look for the colon following constructors, ignore after
  417.      */
  418.  
  419.     if (!strcmp (tokens [close_paren + 1], ":"))
  420.     tcount = close_paren + 1;
  421.  
  422.     /*
  423.      * check for inline prototypes or K & R prototypes
  424.      */
  425.  
  426.     if (close_paren == tcount - 1)
  427.     print_args (stream, open_paren + 1, close_paren - 1);
  428.     else
  429.     print_args (stream, close_paren + 1, tcount - 1);
  430.  
  431.     return (0);
  432. }
  433.  
  434. #define isfluff(c)    (c == '\n' || c == ' ' || c == '\t')
  435.  
  436. void runfile (stream, out_fp)
  437. FILE *stream;
  438. FILE *out_fp;
  439. {
  440.     char buffer[1024];
  441.     char newbuf[1024];
  442.     int infunction;
  443.     int incomment;
  444.     int inmacro;
  445.     int len;
  446.     int i;
  447.     int j;
  448.     int ret;
  449.     char *p;
  450.  
  451.     infunction = 0;
  452.     incomment = 0;
  453.     inmacro = 0;
  454.  
  455.     while (fgets (buffer, sizeof (buffer), stream)) {
  456.     len = strlen (buffer);
  457.  
  458.     while (len > 0 && isfluff (buffer [len - 1]))
  459.         buffer [--len] = 0;
  460.  
  461.     inmacro = 0;
  462.  
  463.     if ((p = strstr (buffer, "//")))
  464.         *p = 0;
  465.  
  466.     if (*buffer == '#' && strstr (buffer, "define")) {
  467.         if (strstr (buffer, "NOFANSI"))
  468.         return;
  469.  
  470.         inmacro = 1;
  471.         if (debug)
  472.         printf ("Skip %s\n", buffer);
  473.         while (buffer [len - 1] == '\\'
  474.         && fgets (buffer, sizeof (buffer), stream)) {
  475.         len = strlen (buffer);
  476.         while (isfluff (buffer [len - 1]))
  477.             buffer [--len] = 0;
  478.  
  479.         if (debug)
  480.             printf ("Skip %s\n", buffer);
  481.         }
  482.     }
  483.  
  484.     if (inmacro)
  485.         continue;
  486.  
  487.     for (j = i = 0; buffer[i]; i++) {
  488.         if (!incomment && buffer[i] == '{') {
  489.         if (!infunction) {
  490.             if ((ret = print_prototype (out_fp)) < 0 && debug)
  491.             printf ("Error %d\n", ret);
  492.             tcount = 0;
  493.         }
  494.         infunction++;
  495.         } else if (!incomment && buffer[i] == '}') {
  496.         infunction--;
  497.         } else {
  498.         if (buffer[i] == '/') {
  499.             if (incomment && i && buffer[i - 1] == '*')
  500.             incomment--;
  501.             else if (buffer[i + 1] == '*')
  502.             incomment++;
  503.         } else {
  504.             if (!infunction && !incomment)
  505.             newbuf[j++] = buffer[i];
  506.         }
  507.         }
  508.     }
  509.     /*printf ("buff = %s %d %d\n", buffer, infunction, incomment);*/
  510.     if (j) {
  511.         newbuf[j] = 0;
  512.         if (debug)
  513.         printf ("Add line %s\n", newbuf);
  514.         if (add_line (newbuf) < 0)
  515.         return;
  516.     }
  517.     }
  518.     if ((ret = print_prototype (out_fp)) < 0 && debug)
  519.     printf ("Error %d\n", ret);
  520.     tcount = 0;
  521. }
  522.  
  523. int main (argc, argv)
  524. int argc;
  525. char **argv;
  526. {
  527.     extern int optopt;
  528.     FILE *stream;
  529.     int errflg = 0;
  530.     int c;
  531.  
  532.     while ((c = getopt (argc, argv, "adesipv")) != -1) {
  533.     switch (c) {
  534.         case 'a':
  535.         doextern = 0;
  536.         douseproto = 0;
  537.         doverbose = 0;
  538.         doapi = 1;
  539.         break;
  540.         case 'd':
  541.         debug = 1;
  542.         break;
  543.         case 'e':
  544.         doextern = 1;
  545.         break;
  546.         case 's':
  547.         dostatic = 1;
  548.         break;
  549.         case 'i':
  550.         dointernal = 1;
  551.         break;
  552.         case 'p':
  553.         douseproto = 0;
  554.         break;
  555.         case 'v':
  556.         doverbose = 0;
  557.         break;
  558.         case ':':
  559.         fprintf(stderr, "Option -%c requires an argument\n", optopt);
  560.         errflg++;
  561.         break;
  562.         case '?':
  563.         fprintf(stderr, "Unrecognized option: - %c\n", optopt);
  564.         errflg++;
  565.         break;
  566.     }
  567.     }
  568.  
  569.     add_token ();
  570.  
  571.     while (optind < argc) {
  572.     if (argv [optind][strlen (argv[optind]) - 1] == 'C') {
  573.         iscxx = 1;
  574.         douseproto = 0;
  575.     } else if (strstr (argv [optind], ".cc")) {
  576.         iscxx = 1;
  577.         douseproto = 0;
  578.     }
  579.  
  580.     if ((stream = fopen (argv [optind], "r"))) {
  581.         if (doverbose)
  582.         print_header (stdout, argv [optind]);
  583.         runfile (stream, stdout);
  584.         fclose (stream);
  585.     } else
  586.         perror (argv [optind]);
  587.  
  588.     optind++;
  589.     }
  590.  
  591.     return (0);
  592. }
  593.